﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data.OleDb;
using System.Data;
using DbSharp.Utils.Db;
using DbSharp.Framework.DbObject;
using DbSharp.Framework.Driver.FieldPersistence;

namespace DbSharp.Framework.Driver
{
    /// <summary>
    /// http://support.microsoft.com/kb/257819#Connect
    /// </summary>
    public class ExcelOleTestPlugin : ITestDataSource
    {

        private const int RECORDSET_ARGUMENT_FLAG = -1;

        #region Private method

        /// <summary>
        /// remove all semicolon symbols tailed the sql statement
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        private string RemoveTailedSemiColons(string sql)
        {
            return SqlTextHelper.RightTrimCharacter(sql, ';');
        }

        private int GetArgumentType(string argumentTypeText)
        {
            int parameterType;
            string upperTypeStr = argumentTypeText.Trim().ToUpper();
            switch (upperTypeStr)
            {
                case "XLS_CHAR":
                    parameterType = (int)OleDbType.VarChar;
                    break;
                case "XLS_NCHAR":
                    parameterType = (int)OleDbType.VarWChar;
                    break;
                case "XLS_DATE":
                    parameterType = (int)OleDbType.Date;
                    break;
                case "XLS_DATETIME":
                    parameterType = (int)OleDbType.DBTimeStamp;
                    break;
                case "XLS_CURRENCY":
                    parameterType = (int)OleDbType.Currency;
                    break;
                case "XLS_DECIMAL":
                    parameterType = (int)OleDbType.Decimal;
                    break;
                case "XLS_DOUBLE":
                    parameterType = (int)OleDbType.Double;
                    break;
                case "XLS_SINGLE":
                    parameterType = (int)OleDbType.Single;
                    break;
                case "XLS_INT":
                    parameterType = (int)OleDbType.Integer;
                    break;
                case "XLS_RECORDSET":
                    parameterType = RECORDSET_ARGUMENT_FLAG;
                    break;
                default:
                    parameterType = (int)OleDbType.VarChar;
                    break;
            }
            return parameterType;
        }


        #endregion



        #region ITestDataSource Members

        public DateTime GetDbServerTime(DbConnection conn)
        {
            return DateTime.Now;
        }


        public bool IsRecordsetTypeArgument(string argumentTypeText)
        {
            int argType = GetArgumentType(argumentTypeText);
            if (argType == RECORDSET_ARGUMENT_FLAG)
                return true;
            else
                return false;
        }

        public bool IsRecordsetTypeParameter(DbParameter param)
        {
            throw new NotSupportedException("Excel driver does not support named parameter.");
        }

        public DbConnection CreateConnection(string connString)
        {
            OleDbConnection conn = new OleDbConnection(connString);
            return conn;
        }


        public string NormalizeArgumentName(string argumentName)
        {
            return argumentName;
        }


        public DbCommand PrepareCommand(IStatementDeclaration statement)
        {
            if (statement.CommandType != CommandType.Text)
                throw new NotSupportedException("Excel driver does not support stored procedure.");

            DbCommand cmd = new OleDbCommand();
            cmd.CommandType = statement.CommandType;
            return cmd;
        }

        public void UpdateCommandText(DbCommand cmd, string newCmdText)
        {
            cmd.CommandText = newCmdText.Trim();
            //make sure the sql statement does not end with semicolon
            cmd.CommandText = RemoveTailedSemiColons(cmd.CommandText);
        }


        public void AssignParameterValue(DbParameter param, string value, string dateTimeFormat)
        {
            //do nothing
        }


        public bool TransactionSupported
        {
            get { return false; }
        }



        public bool HoldResultsetMustWithNamedArgInSP
        {
            get { return false; }
        }






        private IFieldPersistence m_FieldPersistenceService = new ExcelOleFieldPersistence();
        public IFieldPersistence FieldPersistenceService
        {
            get { return m_FieldPersistenceService; }
        }

        #endregion
    }
}
